%% -*- coding: utf-8 -*-

%% @doc パース時の各構文カテゴリのハンドラ。
%%      抽象構文木 (のリスト) を作成する
%%
-module(templ_parse_handler).
-export([init/0]).
-export([text/1,start_if/1,start_let/2,start_foreach/2,else/0,expr/1]).
-export([end_stmt/0,end_if/0,end_let/0,end_foreach/0]).
-export([get_stmt/0,reset_stmt/0]).

-define(STMT_KEY, templ_stmt).

init() -> 
	put(?STMT_KEY, []),
	none.

text([]) -> none;
text(Text) when is_list(Text) ->
	stmt({ok,Text}).
expr({expr,_}=Expr) ->
	stmt(Expr).
stmt(Stmt) ->
	Ss = get_stmt(),
	NewSs = case Ss of
		[]    -> [[Stmt]];
		[S|R] -> [S++[Stmt]|R]
	end,
	put(?STMT_KEY, NewSs).

start_if({expr,_}=Cond) ->
	push_stmt({'if',Cond}).
start_let({name,_,_}=Name, {expr,_}=Value) ->
	push_stmt({'let', Name, Value}).
start_foreach({name,_,_}=Name, {expr,_}=List) ->
	push_stmt({foreach, Name, List}).
push_stmt(Stmt) ->
	Ss = get_stmt(),
	NewSs = case Ss of
		[]    -> [[],{Stmt,[]}];
		[S|R] -> [[],{Stmt,S}|R]
	end,
	put(?STMT_KEY, NewSs).

else() ->
	[_S1,{S2,_S3}|_R] = get_stmt(),
	end_stmt(),
	case S2 of
		{'if',_}      -> push_stmt(elseif);
		{'let',_,_}   -> push_stmt(elselet);
		{foreach,_,_} -> push_stmt(elseforeach)
	end.

end_stmt() ->
	[S1,{S2,S3}|R] = get_stmt(),
	NewSs = [S3++[S2]++[S1]|R],
	put(?STMT_KEY, NewSs).
end_if() ->
	[S1,{S2,S3}|_R] = get_stmt(),
	case S2 of
		{'if',_} -> end_stmt();
		elseif   -> end_stmt();
		_        -> 
			throw({{?MODULE,einval}, [S1,{S2,S3}],"wrong syntax"})
	end.
end_let() ->
	[S1,{S2,S3}|_R] = get_stmt(),
	case S2 of
		{'let',_,_} -> end_stmt();
		elselet     -> end_stmt();
		_           ->
			throw({{?MODULE,einval}, [S1,{S2,S3}],"wrong syntax"})
	end.
end_foreach() ->
	[S1,{S2,S3}|_R] = get_stmt(),
	case S2 of
		{foreach,_,_} -> end_stmt();
		elseforeach   -> end_stmt();
		_             ->
			throw({{?MODULE,einval}, [S1,{S2,S3}],"wrong syntax"})
	end.

get_stmt() ->
	case get(?STMT_KEY) of
		undefined -> [];
		Ss        -> Ss
	end.
reset_stmt() ->
	put(?STMT_KEY, []).
